<?php

namespace Ktnw\WechatSupport\Services;

use Exception;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

/**
 * 微信相关业务类
 */
class WeChatSupportService
{

    /**
     * 获取微信最后的jsapi_ticket
     * @param string $wxKey
     * @return string
     */
    public static function findWxJsapiTicket(string $wxKey): string
    {
        $jsapiTicket = '';
        $where       = [];
        $where[]     = ["wx_key", "=", $wxKey];
        $r           = DB::table(self::getJsapiTicketTableName())->where($where)->orderBy("id", "DESC")->first();
        if ($r) {
            $jsapiTicket = $r->jsapi_ticket;
            $expiresTime = $r->expires_time;
            //判断到期时间是否已经过期
            if (!empty($expiresTime) && time() > strtotime($expiresTime)) {
                $jsapiTicket = '';
            }
        }
        return $jsapiTicket;
    }

    /**
     * 获取微信公众号最后的access_token
     * @param string $wxKey
     * @return string
     */
    public static function findWxAccessToken(string $wxKey): string
    {
        $accessToken = '';
        $where       = [];
        $where[]     = ["wx_key", "=", $wxKey];
        $r           = DB::table(self::getAccessTokenTableName())->where($where)->orderBy("id", "DESC")->first();
        if (!empty($r)) {
            $accessToken = $r->access_token;
            $expiresTime = $r->expires_time;
            // 判断到期时间是否已经过期
            if (!empty($expiresTime) && time() > strtotime($expiresTime)) {
                $accessToken = '';
            }
        }
        return $accessToken;
    }


    /**
     * 保存微信公众号的access_token
     *
     * @param string $wxKey
     * @param string $accessToken
     * @param int $expiresIn 有效期，单位:秒
     */
    public static function saveWxAccessToken(string $wxKey, string $accessToken, int $expiresIn)
    {
        $expires_time         = time() + $expiresIn - 20 * 60;
        $data                 = [];
        $data['wx_key']       = $wxKey;
        $data['access_token'] = $accessToken;
        $data['create_time']  = self::getCurTimeStr();
        $data['expires_time'] = self::timestampToDateStr($expires_time);
        DB::table(self::getAccessTokenTableName())->insertGetId($data);
    }


    /**
     * 保存微信公众号的jsapi_ticket
     *
     * @param string $wxKey
     * @param string $jsapiTicket
     * @param int $expiresIn
     */
    public static function saveWxJsapiTicket(string $wxKey, string $jsapiTicket, int $expiresIn)
    {
        $expiresTime          = time() + $expiresIn - 20 * 60;
        $data                 = [];
        $data['wx_key']       = $wxKey;
        $data['jsapi_ticket'] = $jsapiTicket;
        $data['create_time']  = self::getCurTimeStr();
        $data['expires_time'] = self::timestampToDateStr($expiresTime);
        DB::table(self::getJsapiTicketTableName())->insertGetId($data);
    }

    /**
     * 获取微信用户信息
     * @param string $wxKey
     * @param string $openid
     * @return array
     */
    public static function findWeChatUser(string $wxKey, string $openid): array
    {
        if (empty($openid) || empty($wxKey)) {
            return [];
        }
        $where = ["openid" => $openid, "wx_key" => $wxKey];
        $r     = DB::table(self::getWeChatUserTableName())->where($where)->first();
        return $r ? self::object_to_array($r) : [];
    }

    /**
     * 查询微信用户id
     * @param int $id
     * @return array
     */
    public static function findWeChatUserById(int $id): array
    {
        if (empty($id) || $id < 0) {
            return [];
        }
        $r = DB::table(self::getWeChatUserTableName())->where("id", $id)->first();
        return $r ? self::object_to_array($r) : [];
    }

    /**i
     * 保存微信用户信息
     * @param array $wechatUserParams 微信用户参数
     * @return int 微信用户id
     * @throws Exception
     */
    public static function saveWeChatUser(array $wechatUserParams): int
    {
        if (empty($wechatUserParams) || empty($wechatUserParams["openid"])) {
            throw new Exception("openid 不存在");
        }
        if (empty($wechatUserParams["wx_key"])) {
            throw new Exception("wx key 不能为空");
        }
        $wechatUser = self::findWeChatUser($wechatUserParams["wx_key"], $wechatUserParams["openid"]);
        if ($wechatUser) {
            // 更新
            $id = $wechatUser["id"];
            self::copyArray($wechatUserParams, $wechatUser, true);
            $wechatUser["id"] = $id;
            $wechatUser       = Arr::except($wechatUser, ["create_time"]);
            return DB::table(self::getWeChatUserTableName())->where("id", $id)->update($wechatUser) >= 0 ? $id : 0;
        } else {
            // 新增
            return DB::table(self::getWeChatUserTableName())->insertGetId($wechatUserParams);
        }

    }

    /**
     * 数组拷贝
     * @param array $fromArray
     * @param array $toArray
     * @param bool $isEmptySet 空值是否设置 true-设置; false-不设置;
     * @return array
     */
    public static function copyArray(array $fromArray, array &$toArray, bool $isEmptySet = false): array
    {
        if (empty($fromArray)) {
            return $toArray;
        }
        if (empty($toArray)) {
            return $fromArray;
        }

        foreach ($fromArray as $key => $value) {
            if (!empty($value) || $isEmptySet) {
                $toArray[$key] = $value;
            }
        }

        return $toArray;
    }


    /**
     * 获取微信jsapi_ticket的表名
     * @return string
     */
    private static function getJsapiTicketTableName(): string
    {
        return config("weChatConfig.jsapi_ticket_table_name");
    }


    /**
     * 获取微信access_token的表名
     * @return string
     */
    private static function getAccessTokenTableName(): string
    {
        return config("weChatConfig.access_token_table_name");
    }


    /**
     * 获取微信微信用户的表名
     * @return string
     */
    private static function getWeChatUserTableName(): string
    {
        return config("weChatConfig.wechat_user_table_name");
    }


    /**
     * 获取当前的日期字符串
     */
    private static function getCurDateStr()
    {
        return date("Y-m-d", time());
    }


    /**
     * 获取当前日期的时间字符串
     */
    private static function getCurTimeStr()
    {
        return date("Y-m-d H:i:s", time());
    }

    /**
     * 时间戳转为日期格式
     * @param $timestamp int 时间戳精确到秒
     * @return string
     */
    private static function timestampToDateStr(int $timestamp): string
    {
        return date('Y-m-d H:i:s', $timestamp);
    }

    /**
     * 对象转换数组
     * @param $obj
     * @return array
     */
    private static function object_to_array($obj): array
    {
        if (!is_array($obj) && !is_object($obj)) {
            return $obj;
        }
        $_arr = is_object($obj) ? get_object_vars($obj) : $obj;
        $arr  = [];
        foreach ($_arr as $key => $val) {
            $val       = (is_array($val)) || is_object($val) ? self::object_to_array($val) : $val;
            $arr[$key] = $val;
        }
        return $arr;
    }


}
